/*
 *Copyright (c) [2019-2020]  C2comm, Inc.  All rights reserved.
 *
 *This program is free software; you can redistribute it and/or
 *modify it under the terms of the GNU General Public License
 *as published by the Free Software Foundation; either version 2
 *of the License, or (at your option) any later version.
 *
 *This program is distributed in the hope that it will be useful,
 *but WITHOUT ANY WARRANTY; without even the implied warranty of
 *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *GNU General Public License for more details.
 *
 *You should have received a copy of the GNU General Public License
 *along with this program; If not, see <https://www.gnu.org/licenses/>
 */
/*
 *Vendor: C2comm
 *Version: 1.0
 *Filename: SMTimeOutControl.v
 *Target Device: Altera
 *Author : sunxiaotian@c2comm.cn
*/

`timescale 1ns/1ps
module SMTimeOutControl(
    input  wire         SYS2CORE_clk,
    input  wire         SYS2CORE_rst_n,
    input  wire [76:0]  G_current_state,
    input  wire [348:0] CONF2CORE_sm_static_conf,
	
	output reg        TOC2SC_time_out,
	
	output wire [332:0]   CORE2MON_sm_state
    
);
//***************************************************
//            Intermediate variable Declaration
//***************************************************
//all wire/reg/parameter variable 
//should be declare below here 
reg [ 1:0] sm_listen_param_set;//
reg [19:0] curr_local_time;
reg [19:0] next_local_time;


localparam SM_INTEGRATE             = 8'b0000_0001,
		   SM_WAIT_4_CYCLE_START    = 8'b0000_0010,
		   SM_UNSYNC                = 8'b0000_0100,
		   SM_FLOOD                 = 8'b0000_1000,
		   SM_WAIT_4_CYCLE_START_CS = 8'b0001_0000,
		   SM_TENTATIVE_SYNC        = 8'b0010_0000,
		   SM_SYNC                  = 8'b0100_0000,
		   SM_STABLE                = 8'b1000_0000;

		   
assign  CORE2MON_sm_state[285:0] = 286'b0;	
assign  CORE2MON_sm_state[286:286] = TOC2SC_time_out;   
assign  CORE2MON_sm_state[306:287] = curr_local_time[19:0];
assign  CORE2MON_sm_state[332:307] = 26'b0;


always @(*) begin
	if(((G_current_state[76:69] == SM_INTEGRATE) && (G_current_state[65] == 1'b1 ))|| 
	   ((G_current_state[76:69] == SM_UNSYNC) && (G_current_state[50] == 1'b1 ))|| 
	   ((G_current_state[76:69] == SM_FLOOD) && (G_current_state[44] == 1'b1 )) 
	) begin
		next_local_time[19:0] = CONF2CORE_sm_static_conf[187:168];
	end
	else if(((G_current_state[76:69] == SM_INTEGRATE) && (G_current_state[66] == 1'b1 ))|| 
			((G_current_state[76:69] == SM_UNSYNC) && (G_current_state[53] == 1'b1 ))|| 
			((G_current_state[76:69] == SM_FLOOD) && (G_current_state[46] == 1'b1 ))|| 
			((G_current_state[76:69] == SM_WAIT_4_CYCLE_START_CS) && (G_current_state[38] == 1'b1 ))|| 
			((G_current_state[76:69] == SM_TENTATIVE_SYNC) && (G_current_state[32] == 1'b1 ))|| 
			((G_current_state[76:69] == SM_SYNC) && (G_current_state[21] == 1'b1 ))|| 
			((G_current_state[76:69] == SM_STABLE) && (G_current_state[9] == 1'b1 )) 
	) begin
		next_local_time[19:0] = CONF2CORE_sm_static_conf[243:224]; 
	end
	else if(((G_current_state[76:69] == SM_INTEGRATE) && (G_current_state[67] == 1'b1 ))
	) begin
		next_local_time[19:0] = CONF2CORE_sm_static_conf[329:310]; 
	end
	else if(((G_current_state[76:69] == SM_UNSYNC) && (G_current_state[51] == 1'b1 ))|| 
			((G_current_state[76:69] == SM_UNSYNC) && (G_current_state[52] == 1'b1 ))|| 
			((G_current_state[76:69] == SM_FLOOD) && (G_current_state[45] == 1'b1 ))|| 
			((G_current_state[76:69] == SM_WAIT_4_CYCLE_START_CS) && (G_current_state[37] == 1'b1 ))
	) begin
		next_local_time[19:0] = CONF2CORE_sm_static_conf[263:244];
	end
	else if(((G_current_state[76:69] == SM_FLOOD) && (G_current_state[42] == 1'b1 )) 
	) begin
		next_local_time[19:0] = CONF2CORE_sm_static_conf[283:264] - CONF2CORE_sm_static_conf[303:285]; 
	end
	else if(((G_current_state[76:69] == SM_FLOOD) && (G_current_state[43] == 1'b1 )) 
	) begin
		next_local_time[19:0] = CONF2CORE_sm_static_conf[303:284]; 
	end
	else if(((G_current_state[76:69] == SM_TENTATIVE_SYNC) && (G_current_state[25] == 1'b1 ))|| 
			((G_current_state[76:69] == SM_TENTATIVE_SYNC) && (G_current_state[27] == 1'b1 ))|| 
			((G_current_state[76:69] == SM_SYNC) && (G_current_state[13] == 1'b1 ))|| 
			((G_current_state[76:69] == SM_SYNC) && (G_current_state[15] == 1'b1 ))|| 
			((G_current_state[76:69] == SM_SYNC) && (G_current_state[16] == 1'b1 ))|| 
			((G_current_state[76:69] == SM_STABLE) && (G_current_state[3] == 1'b1 ))|| 
			((G_current_state[76:69] == SM_STABLE) && (G_current_state[6] == 1'b1 )) 
	) begin
		next_local_time[19:0] = CONF2CORE_sm_static_conf[167:148]; 
	end
	else begin
		next_local_time = (curr_local_time == 20'b0) ? curr_local_time : curr_local_time - 1'b1;
	end
end





always @(posedge SYS2CORE_clk or negedge SYS2CORE_rst_n) begin
    if(~SYS2CORE_rst_n) begin
		 sm_listen_param_set <= 2'b11;
	 end
	 else begin
		 sm_listen_param_set <= {sm_listen_param_set[0],1'b0};
	 end
end


always @(posedge SYS2CORE_clk or negedge SYS2CORE_rst_n) begin
    if(~SYS2CORE_rst_n) begin
        curr_local_time <= 20'hFFFFF;
    end
	 else if(sm_listen_param_set>2'd0) begin
		  curr_local_time <= CONF2CORE_sm_static_conf[207:188]; 
	 end
    else begin
        curr_local_time[19:0] <= next_local_time[19:0] ;
    end
end

//超时信号
always @(posedge SYS2CORE_clk or negedge SYS2CORE_rst_n) begin
    if(~SYS2CORE_rst_n) begin
        TOC2SC_time_out <= 1'b0;
    end
    else begin
        TOC2SC_time_out <= ((curr_local_time[19:0]  == 20'b0) || (next_local_time[19:0]  == 20'b0));
    end
end


endmodule